package com.example.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.example.dao.UserDao;
import com.example.entity.*;
import com.example.exception.CustomException;
import com.example.common.JwtTokenUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class UserService {

    @Resource
    private UserDao userDao;
//    @Resource
    private EmailService emailService;

    private final StringRedisTemplate redisTemplate;

    @Autowired
    public UserService(EmailService emailService, StringRedisTemplate redisTemplate) {
        this.emailService = emailService;
        this.redisTemplate = redisTemplate;
    }

    //=====================================================================
    public void add(User user) {
        //对用户账号和用户名进行非空判断
        if(user.getAccount() == null || user.getAccount().equals("") || user.getUsername() == null || user.getUsername().equals("") || user.getEmail() == null ||
        user.getEmail().equals("")){
            throw new CustomException("还有栏目未进行填写,请检查！");
        }

        //进行重复性判断 同一名字的用户不允许重复新增  只要根据用户账号去数据库查询一下就可以了
        User userlist = userDao.findByAccount(user.getAccount());
        if(userlist != null){
            //说明数据库中有该账户
            throw new CustomException("该用户名已存在");
        }

        //没有密码
        if(user.getPassword() == null){
            throw new CustomException("密码不能为空！");
        }
        userDao.add(user);
    }

    public void update(User user) {
        userDao.update(user);
    }

    public void del(Integer userId) {
        userDao.deleteById(userId);
    }

    //==============================================================
    public User login(User user) {
        // 1. 先进行一些非空判断
        if(user.getAccount() == null || user.getAccount().isEmpty() || user.getPassword() == null || user.getPassword().isEmpty()){
            throw new CustomException("账号或密码不能为空！");
        }
        // 2. 在数据库中根据用户账号和密码进行查询用户信息
        User userlist = userDao.findByAccountAndPaassword(user.getAccount(),user.getPassword(),user.getIdentity());
        //查出来没有说明账号密码输入错误或者账号不存在
        if(userlist == null){
            throw new CustomException("账号密码输入错误或账号不存在");
        }
        // 3. 如果有,则经过校验后可进行登录 没有则返回错误信息(账号或密码输入有误)
        //生成该登录用户对应的Token 然后跟着user一起返回到前台
        String token = JwtTokenUtils.getToken(userlist.getUserId().toString(),userlist.getPassword());
        userlist.setToken(token);
        return userlist;
    }

    //解析token时查找用户信息
    public User findById(Integer userId) {
        return userDao.selectById(userId);      //根据主键 id 查询用户信息
    }

    public PageInfo<User> searchUser(Params params) {
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        //接下来的查询会按照当前的分页设置自动进行查询
        List<User> list = userDao.searchUser(params);
        return PageInfo.of(list);
    }

    public PageInfo<User> searchBusiness(Params params) {
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        //接下来的查询会按照当前的分页设置自动进行查询
        List<User> list = userDao.searchBusiness(params);
        return PageInfo.of(list);
    }

    public List<ShopInfo> findshop(ShopInfo shopInfo) {
        List<ShopInfo> info = userDao.findshop(shopInfo);
        return info;
    }

    //查询树苗数量======================================================
    public ShopInfo findnum(ShopInfo shopInfo) {

        ShopInfo info = userDao.findnum(shopInfo);

        return info;
    }

    public User reloadUser(User user) {
        User userinfo = userDao.reloadUser(user);
        //从请求头中获取token
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("token");
        userinfo.setToken(token);
        return userinfo;
    }

    public void updateImg(User user) {
        userDao.uploadImg(user);
    }

    //======================================================
    public void checkEmail(String email,String useraccount) {

        User user = userDao.findByAccount(useraccount);
        //先进行账号和邮箱的匹配 成功则进入下一步
        if (user == null || !email.equals(user.getEmail())) {
            throw new CustomException("用户账号与邮箱不匹配");
        } else {
            //1.生成一个5位验证码
            String emailcode = RandomUtil.randomNumbers(5);
            //2.将验证码保存到redis中 5分钟
            redisTemplate.opsForValue().set(email,emailcode,5,TimeUnit.MINUTES);
            //3.发送携带验证码的邮件到指定邮箱
            emailService.sendSimpleMail(email,"忘记密码的邮箱验证码",emailcode);
        }

    }

    //检查用于重置密码的验证码是否输入正确==============================================
    public void checkCode(String mailcode,User user) {
        //前端对验证码已经进行了非空判断
        //拿到redis存储的code
        String rediscode = redisTemplate.opsForValue().get(user.getEmail());
        if (!Objects.equals(rediscode, mailcode)) {
            //验证码错误则抛出异常
            throw new CustomException("验证码输入错误");
        } else {
            //啥也不干
        }
    }

    //重置密码==========================================
    public void resetpwd(String account, String newPassword) {
        userDao.resetpwd(account,newPassword);
    }

    //查询审核表信息=======================================================
    public PageInfo<CheckInfo> findCheckInfo(Params params) {
        //开启分页查询
        PageHelper.startPage(params.getPageNum(),params.getPageSize());
        //接下来的查询会按照当前的分页设置自动进行查询
        List<CheckInfo> list = userDao.findCheckInfo(params);
        return PageInfo.of(list);
    }

    //审核通过==============================================================
    public void checkAgree(User user,Integer checkId) {
        Check check = new Check(checkId,DateUtil.now(),user.getUsername(),1);
        userDao.checkAgree(check);

        //通过checkId找到对应的Check表中的一条记录 从中获取新商家的用户信息(account，username，pwd，email)
        Check check1 = userDao.findByCheckId(checkId);
        //下一步是更新商家表 从redis取出商家密码
        String pwd = redisTemplate.opsForValue().get(check1.getAccount());
        //将新商家信息写入数据库user表
        User newuser = new User(null,check1.getAccount(),check1.getUsername(),pwd,check1.getEmail(),2,"",0);
        userDao.addNewUser(newuser);
        //将商家的店铺信息写入shop表
        ShopInfo shopInfo = new ShopInfo(null,check1.getShopname(),check1.getUsername(),DateUtil.now());
        userDao.addshop(shopInfo);
        //录入商家信息后通过商家邮箱通知商家 发送邮件到指定邮箱
        emailService.sendSimpleMail(newuser.getEmail(), "树苗易管理系统申请商家审核通过，下面是您的账号和密码","账号:"+ newuser.getAccount() + "\n密码:" + newuser.getPassword());

    }

    //把传来的数据存入审核表============================================
    public void storagenewshopper(User user,String shopName) {
        Check checkinfo = new Check(null,user.getAccount(),user.getUsername(),shopName,user.getEmail(),null,null,0);
        userDao.storagenewshopper(checkinfo);
    }

    //审核中拒绝商家后 到数据库中修改审核状态为 2 拒绝商家注册======================================
    public void checkReject(User user,Integer checkId) {
        //修改数据库的check表中的数据
        Check check = new Check(checkId,DateUtil.now(),user.getUsername(),2);
        userDao.checkReject(check);
        //发送邮件通知商家注册失败

        //通过checkId找到对应的Check表中的一条记录 从中获取新商家的邮箱地址
        String email = userDao.findByCheckId(checkId).getEmail();

        //录入商家信息后通过商家邮箱通知商家 发送邮件到指定邮箱
        emailService.sendSimpleMail(email,"审核申请已受理", "很抱歉，您在树苗易管理系统中提交的商家申请已被拒绝");
    }

    //加载系统商家数量
    public int loadShopperNumber() {
        return userDao.loadShopperNumber();
    }

    //注销用户信息
    public void deletetUserByUserId(Integer userId) {
        userDao.deletetUserByUserId(userId);
    }
}
